package com.gitee.wsl.net.udp.model


import kotlinx.io.Buffer
import kotlinx.io.readByteArray

// "In the absence of these mechanisms, QUIC endpoints SHOULD NOT send IP
//   packets larger than 1280 bytes.  Assuming the minimum IP header size,
//   this results in a QUIC maximum packet size of 1232 bytes for IPv6 and
//   1252 bytes for IPv4."
// As it is not know (yet) whether running over IP4 or IP6, take the smallest of the two:
const val MAX_PACKET_SIZE: Int = 1232

@Suppress("ArrayInDataClass")
internal data class Packet(
    val packetNumber: Long,
    val shouldBeAcked: Boolean,
    val bytes: ByteArray
)

internal fun createDataPacket(
    packetNumber: Long, data: ByteArray
): Packet {
    val buffer = Buffer()
    buffer.writeByte(0x03.toByte())
    buffer.writeLong(packetNumber)
    buffer.write(data)

    require(buffer.size <= MAX_PACKET_SIZE) { "Invalid packet size" }
    return Packet(packetNumber, true, buffer.readByteArray())
}


internal fun createClosePacket(
    transportError: TransportError = TransportError(
        TransportError.Code.NO_ERROR
    )
): Packet {

    val buffer = Buffer()
    buffer.writeByte(0x04.toByte())
    buffer.writeLong(4)
    buffer.writeLong(transportError.errorCode())

    require(buffer.size <= MAX_PACKET_SIZE) { "Invalid packet size" }
    return Packet(4, false, buffer.readByteArray())
}


internal fun createAckPacket(
    packet: Long
): Packet {
    val buffer = Buffer()
    buffer.writeByte(0x02.toByte()) // only AckFrame of payloadType 0x02 is supported
    buffer.writeLong(2)
    buffer.writeLong(packet)
    return Packet(2, false, buffer.readByteArray())
}


internal fun createPingPacket(
): Packet {
    val buffer = Buffer()
    buffer.writeByte(0x01.toByte())
    buffer.writeLong(0)
    return Packet(0, true, buffer.readByteArray())
}

